/* Iterator 遍历器接口 实际上是一个指针对象，对js中部署了此接口的数据结构进行统一的遍历 */
let { log } = console
// 1. 使用迭代器遍历数组
let f1 = () => {
  let arr = [1, 2, 3, 4]
  // 模拟数组迭代器方法
  function makeIterator(arr) {
    let index = 0
    return {
      next() {
        return index < arr.length ? { value: arr[index++], done: false } : { value: null, done: true }
      },
    }
  }
  // 遍历数组元素
  let iterator = makeIterator(arr)
  // while (1) {
  //   let rt = iterator.next()
  //   if (rt.done) {
  //     break
  //   }
  //   log(rt.value)
  // }
  // 获得数组迭代器
  let it = arr[Symbol.iterator]()
  while (1) {
    let rt = it.next()
    if (rt.done) {
      break
    }
    log(rt.value)
  }
}

// 2. 使用迭代遍历set集合
let f2 = () => {
  let set = new Set()
  set.add(1)
  set.add(2)
  set.add(3)
  set.add(4)
  // 获得set对象的迭代器
  let it = set[Symbol.iterator]()
  // 遍历迭代器的方法
  // for (let item of it) {
  //   log(item)
  // }
  // 使用while遍历
  while (1) {
    let rt = it.next()
    if (rt.done) {
      break
    }
    log(rt.value)
  }
}

// 3. 使用迭代器遍历map
let f3 = () => {
  let map = new Map([
    ['a', 1],
    ['b', 2],
  ])
  for (let [k, v] of map[Symbol.iterator]()) {
    log(k, v)
  }
}

// 4. 使用迭代器遍历字符串
let f4 = () => {
  let str = 'Microsoft Corporation'
  for (let item of str[Symbol.iterator]()) {
    log(item)
  }
}

// 5. 使用迭代器遍历对象
let f5 = () => {
  // 自定义的对象是没有迭代器属性
  let stu = {
    id: 1,
    name: 'tom',
    age: 20,
    info() {},
    // 对象部署迭代器
    [Symbol.iterator]: function () {
      let _this = this
      let index = 0
      let keys = Object.keys(this)
      return {
        next() {
          if (index < keys.length) {
            let k = keys[index]
            let v = _this[k]
            index++
            return {
              value: [k, v],
              done: false,
            }
          }
          return {
            value: [],
            done: true,
          }
        },
      }
    },
  }
  // 使用迭代器遍历对象的属性和属性值
  for (let [k, v] of stu) {
    log(k, v)
  }
}
f5()
